/**
 * ApiHepler.java
 * 
 * Purpose              : Manage all api call.
 * 
 * Optional info        : 
 *
 * @author              : Hoang Viet 
 * 
 * @date                : Apr 9, 2012
 * 
 * @lastChangedRevision : 
 *
 * @lastChangedDate     :
 *
 */
package com.applink.sell_proof.api;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;

import com.applink.sell_proof.EMarketing;
import com.applink.sell_proof.constant.Constant;
import com.applink.sell_proof.constant.ItemStatus;
import com.applink.sell_proof.database.table.AnalyticDBHelper;
import com.applink.sell_proof.database.table.ClaimDBHelper;
import com.applink.sell_proof.database.table.ProductModelDBHelper;
import com.applink.sell_proof.database.table.ProjectDBHelper;
import com.applink.sell_proof.database.table.QuestionDBHelper;
import com.applink.sell_proof.database.table.SPreferences;
import com.applink.sell_proof.model.Claim;
import com.applink.sell_proof.model.ClaimImage;
import com.applink.sell_proof.model.Product;
import com.applink.sell_proof.model.Project;
import com.applink.sell_proof.model.Quiz;
import com.applink.sell_proof.model.Redeem;
import com.applink.sell_proof.model.Tip;
import com.applink.sell_proof.model.UserProfile;
import com.applink.sell_proof.util.Utility;

public class DataHelper extends Observable {

	private static final String TAG = "DataHelper_LOG";

	private final int MAX_SIZE_POOL = 10;

	private volatile static DataHelper uniqueInstance;

	private final int TIME_OUT_CONNECTION = 50000;

	public static final int INITIAL_SIZE = 15;

	private boolean checkModelNo = false;
	private boolean checkServiceTag = false;
	private int positionServiceTag = 0;

	private Map<String, HttpTask> mPoolExcutingTask;
	private Queue<HttpTask> mWaitingTask;

	private ArrayList<Long> timeStamp = new ArrayList<Long>();

	public static DataHelper getInstance() {
		if (uniqueInstance == null) {
			synchronized (DataHelper.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new DataHelper();
				}
			}
		}
		return uniqueInstance;
	}

	private DataHelper() {
		super();
		mPoolExcutingTask = new LinkedHashMap<String, DataHelper.HttpTask>(
				MAX_SIZE_POOL) {

			private static final long serialVersionUID = 1841232605820933953L;

			@Override
			protected boolean removeEldestEntry(
					java.util.Map.Entry<String, HttpTask> eldest) {
				if (size() > MAX_SIZE_POOL) {
					Log.e(TAG, "remove eldest task "
							+ eldest.getValue().getUrl()
							+ " current size is : " + size());
					eldest.getValue().disconect();
					return true;
				} else {
					return false;
				}
			}
		};
		mWaitingTask = new ConcurrentLinkedQueue<DataHelper.HttpTask>();
	}

	public String ConvertStreamToString(InputStream is) {
		if (is != null) {
			Writer writer = new StringWriter();
			char[] buffer = new char[1024];
			try {
				Reader reader = new BufferedReader(new InputStreamReader(is,
						"UTF-8"));
				int n;
				while ((n = reader.read(buffer)) != -1) {
					writer.write(buffer, 0, n);
				}
			} catch (IOException e) {
				return "";
			}
			return writer.toString();
		} else {
			return "";
		}
	}

	@SuppressLint("NewApi")
	private void excute(String url, MethodParams methodparam) {
		if (mPoolExcutingTask.get(url) == null) {
			HttpTask task = new HttpTask(url, methodparam);
			mPoolExcutingTask.put(url, task);
			if (android.os.Build.VERSION.SDK_INT >= 11) {
				task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
						(Void) null);
			} else {
				task.execute((Void) null);
			}
		}
		Log.e(TAG, url + " current size : " + mPoolExcutingTask.size()
				+ " obs=" + DataHelper.getInstance().countObservers());

	}

	@SuppressLint("NewApi")
	private void excute(String url, String data, MethodParams methodparam) {
		if (mPoolExcutingTask.get(url) == null) {
			HttpTask task = new HttpTask(url, methodparam, data);
			mPoolExcutingTask.put(url, task);
			if (android.os.Build.VERSION.SDK_INT >= 11) {
				task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
						(Void) null);
			} else {
				task.execute((Void) null);
			}
		}
	}

	public void getAllProduct() {
		String token = EMarketing.getInstance().getAccessCode();// EMarketing.getInstance().getJsonAccountToken();
		excute(Urls.GET_PRODUCT + token,
				new MethodParams(Methods.getAllProduct));
	}

	public void getAllDistributor() {
		String token = EMarketing.getInstance().getAccessCode();// EMarketing.getInstance().getJsonAccountToken();
		String jsonToken = String.format("%s{\"token\":\"%s\"}",
				Urls.GET_DISTRIBUTOR, token);
		excute(jsonToken, new MethodParams(Methods.getAllDistributor));
	}

	public void getAllCountry() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		excute(Urls.GET_COUNTRIES + token, new MethodParams(
				Methods.getAllCountry));
	}

	public void updateUserActivity() {

		ConcurrentHashMap<String, HashMap<String, Object>> records = AnalyticDBHelper
				.getAllRecords();

		if (records == null)
			return;

		if (records.size() < 1)
			return;

		MethodParams methodParam = new MethodParams(Methods.updateUserActivity);

		String token = EMarketing.getInstance().getJsonAccountToken();

		JSONArray arrayRecord = new JSONArray();

		for (HashMap<String, Object> r : records.values()) {

			Map<String, String> param = new HashMap<String, String>();

			// param.put("RecordID", (String) r.get(AnalyticDBHelper.ID));

			// param.put("RecordType", (String)
			// r.get(AnalyticDBHelper.RECORD_TAG));

			String date = "";
			long time = (Long) r.get(AnalyticDBHelper.RECORD_TIME);

			boolean isSatisfied = checkSatisfiedWithOtherTimes(time);
			if (isSatisfied == true) {

				this.timeStamp.add(time);

				if (time != 0) {
					Calendar cal = Calendar.getInstance();
					cal.setTimeInMillis(time);
					date = String.format("%s-%s-%s %s:%s:%s",
							cal.get(Calendar.MONTH) + 1,
							cal.get(Calendar.DAY_OF_MONTH),
							cal.get(Calendar.YEAR),
							cal.get(Calendar.HOUR_OF_DAY),
							cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
				}

				param.put("RecordTime", date);

				param.put("UserID", (String) r.get(Constant.ACCOUNT_ID));

				JSONObject jsonRecordValue = new JSONObject(param);
				arrayRecord.put(jsonRecordValue);
			}
		}

		excute(Urls.UPDATE_USER_ACTIVITY,
				String.format("token=%s&activityList=%s", token,
						arrayRecord.toString()), methodParam);
	}

	private boolean checkSatisfiedWithOtherTimes(long time) {
		boolean isSatisfied = true;

		for (int i = 0; i < this.timeStamp.size(); i++) {
			System.out.println("<<<<<  timeStamp = " + this.timeStamp.get(i)
					+ "comparedtime= " + time);
			System.out.println("<<<<<  "
					+ Math.abs(this.timeStamp.get(i) - time));
			if (Math.abs(this.timeStamp.get(i) - time) < 900000) {
				return false;
			}
		}
		return isSatisfied;
	}

	public void getTips(int offset, int size, Tip.Category category) {

		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> maps = new HashMap<String, String>();

		maps.put("PartnerID", EMarketing.getInstance().getAccountId());
		maps.put("position", Integer.toString(offset));
		maps.put("size", Integer.toString(size));
		maps.put("TipCategoryID", Integer.toString(category.toInt()));

		JSONObject valueJson = new JSONObject(maps);
		String url = String.format(Urls.GET_TIPS, valueJson.toString(), token);
		MethodParams params = new MethodParams(Methods.getTips, offset, size);
		params.setInputData(category);
		excute(url, params);

	}

	public void getTipDetail(long tipId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		excute(String.format(Urls.GET_TIP_DETAIL, tipId, token),
				new MethodParams(Methods.getTipDetail));
	}

	public void getAllQuiz(int position, int size, Quiz.Category type) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("PartnerID", EMarketing.getInstance().getAccountId());
		map.put("QuizCategoryID", Integer.toString(type.toInt()));
		map.put("position", Integer.toString(position));
		map.put("size", Integer.toString(size));
		JSONObject param = new JSONObject(map);
		String token = EMarketing.getInstance().getJsonAccountToken();
		MethodParams methodparam = new MethodParams(Methods.getAllQuiz);
		methodparam.setInputData(type);
		excute(String.format(Urls.GET_ALL_QUIZ, param.toString(), token),
				methodparam);
	}

	public void getQuizDetail(long quizId) {
		List<Long> questionIds = QuestionDBHelper
				.getListQuestionIdInQuiz(quizId);
		if (questionIds != null) {
			DataResult result = new DataResult(questionIds);
			result.setMethodParam(new MethodParams(Methods.getQuizDetail));
			setChanged();
			notifyObservers(result);
			return;
		}

		Map<String, String> params = new HashMap<String, String>();
		params.put("QuizReply.QuizCampaignID", Long.toString(quizId));
		params.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(params);
		MethodParams methodParam = new MethodParams(Methods.getQuizDetail);
		methodParam.setInputData(quizId);
		excute(String.format(Urls.GET_QUIZ_DETAIL, json.toString(), EMarketing
				.getInstance().getJsonAccountToken()), methodParam);
	}

	public void replyQuiz(long quizId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<Long, String> mapAnswer = QuestionDBHelper
				.getAllAnswerIdAndUserReplyInQuiz(quizId);
		if (mapAnswer != null) {
			JSONArray arrayId = new JSONArray(mapAnswer.keySet());

			String arrayIdParam = String.format("\"QuizReplyDetailID\":%s",
					arrayId.toString());

			String submittedCampaign = String.format(
					"\"QuizCampaignID\":%s,\"PartnerID\":%s", Long
							.toString(quizId), EMarketing.getInstance()
							.getAccountId());

			JSONArray arrayUserReply = new JSONArray(mapAnswer.values());
			String userReplyParam = String.format("\"UserReply\":%s",
					arrayUserReply.toString());
			Log.e(TAG, userReplyParam);
			String data = String
					.format("ids={%s}&jsonColumnValue={%s}&token=%s&submittedCampainID={%s}",
							arrayIdParam, userReplyParam, token,
							submittedCampaign);
			Log.e(TAG, data);
			excute(Urls.REPLY_QUIZ, data, new MethodParams(Methods.replyQuiz));

		}
	}

	public void getCustomerSupport() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String.format(Urls.GET_CUSTOMERSUPPORT,
				"\"CustCountryID\"", "\"3\"", token);
		excute(data, new MethodParams(Methods.getCustomerProduct));
	}

	public void getUserSetting() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// DataResult result = ParserDataHelper.getInstance().parse(content,
		// methodParams);
		// String data = String.format(Urls.GET_USERINFOR, "\"ContactID\"",
		// "\"69\"", token);
		String data = String.format(Urls.GET_USERINFOR, "\"ContactID\"", "\""
				+ EMarketing.getInstance().getContactID() + "\"", token);
		System.out.println(">>>> data = " + data);
		excute(data, new MethodParams(Methods.getCustomerInfor));
	}

	public void getListProgramType() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String.format(
				"{\"CampaignContact.CandidateContactID\":%s}", EMarketing
						.getInstance().getAccountId());
		excute(Urls.GET_TYPE_PROGRAM,
				String.format("jsonValue=%s&token=%s", data, token),
				new MethodParams(Methods.getAllCampaign));
	}

	public void getListProgramByCampaing(long campaignId, String campaignName) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String
				.format("{\"CampaignContact.CandidateContactID\":%s,\"Campaign.RewardTypeID\":%s}",
						EMarketing.getInstance().getAccountId(), campaignId);
		MethodParams methodParam = new MethodParams(
				Methods.getAllProgramByCompaign);
		methodParam.setInputData(campaignName);
		excute(String.format(Urls.GET_LIST_PROGRAM, data, token), methodParam);
	}

	public void getEarnedRewardByCampaing(long campaignId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String.format(
				"{\"CandidateContactID\":%s,\"RewardTypeID\":%s}", EMarketing
						.getInstance().getAccountId(), campaignId);
		excute(String.format(Urls.GET_EARNED_REWAED_BY_PROGRAM, data, token),
				new MethodParams(Methods.getEarnedRewardByCampaign));
	}

	public void getProgramDetail(long programId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String
				.format("{\"CampaignContact.CandidateContactID\":%s,\"CampaignContact.CampaignID\":%s}",
						EMarketing.getInstance().getAccountId(), programId);
		excute(String.format(Urls.GET_PROGRAM_DEATAIL, data, token),
				new MethodParams(Methods.getProgramDetail));
	}

	public void getEarnedStatement() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String.format("{\"CandidateContactID\":%s}", EMarketing
				.getInstance().getAccountId());
		excute(String.format(Urls.GET_EARNED_STATEMENT, data, token),
				new MethodParams(Methods.getEarnedStatement));
	}

	public void getListRedeem() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		String data = String.format("{\"CandidateContactID\":%s}", EMarketing
				.getInstance().getAccountId());
		excute(String.format(Urls.GET_PREVIOUS_REDEEM, data, token),
				new MethodParams(Methods.getPreviousRedeem));
	}

	public void updateUserProfile(UserProfile userProfile) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> params = new HashMap<String, String>();
		params.put(Constant.USPF_DESIGNATION, userProfile.getDesignation());
		params.put(Constant.USPF_EMAIL, userProfile.getEmail());
		params.put(Constant.USPF_MOBILE, userProfile.getMobileNo());

		String json = new JSONObject(params).toString();

		String data = String.format(
				"contactIDJson=%s&updateValueJson=%s&token=%s", EMarketing
						.getInstance().getAccountId(), json, token);
		excute(Urls.UPDATE_USERPROFILE, data, new MethodParams(
				Methods.updateUserProfile));

	}

	public void updateOfficeProfile(UserProfile officeProfile) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> params = new HashMap<String, String>();
		params.put(Constant.OFFICE_COUNTRYCODE,
				Integer.toString(officeProfile.getOffAddCountryCode()));
		params.put(Constant.OFFICE_COUNTRY,
				officeProfile.getOffAddCountryName());
		params.put(Constant.OFFICE_POSTALCODE,
				officeProfile.getOffAddPostalCode());
		params.put(Constant.OFFICE_STREETNAME,
				officeProfile.getOffAddStreetName());
		params.put(Constant.OFFICE_UNIT, officeProfile.getOffAddUnit());
		params.put(Constant.OFFICE_BUILDNAME,
				officeProfile.getOffAddBuildName());

		String json = new JSONObject(params).toString();

		String data = String.format(
				"contactIDJson=%s&updateValueJson=%s&token=%s", EMarketing
						.getInstance().getAccountId(), json, token);
		excute(Urls.UPDATE_USERPROFILE, data, new MethodParams(
				Methods.updateUserProfile));

	}

	public void updateDeliveryProfile(UserProfile deliveryProfile) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> params = new HashMap<String, String>();
		params.put(Constant.DELIVERY_COUNTRYCODE,
				Integer.toString(deliveryProfile.getDeliAddCountryCode()));
		params.put(Constant.DELIVERY_COUNTRY,
				deliveryProfile.getDeliAddCountryName());
		params.put(Constant.DELIVERY_POSTALCODE,
				deliveryProfile.getDeliAddPostalCode());
		params.put(Constant.DELIVERY_STREETNAME,
				deliveryProfile.getDeliAddStreetName());
		params.put(Constant.DELIVERY_UNIT, deliveryProfile.getDeliAddUnit());
		params.put(Constant.DELIVERY_BUILDNAME,
				deliveryProfile.getDeliAddBuildName());

		String json = new JSONObject(params).toString();

		String data = String.format(
				"contactIDJson=%s&updateValueJson=%s&token=%s", EMarketing
						.getInstance().getAccountId(), json, token);
		excute(Urls.UPDATE_USERPROFILE, data, new MethodParams(
				Methods.updateUserProfile));

	}

	public void saveRedeem(Redeem redeem) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> paramsRedeem = new HashMap<String, String>();
		paramsRedeem.put("RedeemedPoints", Integer.toString(redeem.getPoint()));
		paramsRedeem.put("CampaignContactID", EMarketing.getInstance()
				.getAccountId());
		paramsRedeem.put("TierLevelID", Long.toString(redeem.getId()));
		String jsonRedeem = new JSONObject(paramsRedeem).toString();

		Map<String, String> paramsReceiver = new HashMap<String, String>();
		paramsReceiver.put("StreetnameDelivery", redeem.getStreet());
		paramsReceiver.put("BuildingnameDelivery", redeem.getBuilding());
		paramsReceiver.put("UnitnameDelivery", redeem.getUnit());
		paramsReceiver.put("PostalCodeDelivery", redeem.getPostalCode());
		paramsReceiver.put("DeliveryLastName", redeem.getLastName());
		paramsReceiver.put("DeliveryFirstName", redeem.getLastName());
		paramsReceiver.put("DeliveryEmail1", redeem.getEmail());
		paramsReceiver.put("DeliveryMobile1", redeem.getMobile());
		paramsReceiver.put("CountryDeliveryID",
				Long.toString(redeem.getCountryId()));
		String jsonReceiver = new JSONObject(paramsReceiver).toString();

		excute(Urls.SAVE_REDEEM, String.format(
				"redeemValue=%s&userprofileValue=%s&token=%s", jsonRedeem,
				jsonReceiver, token), new MethodParams(Methods.saveRedeem));
	}

	public void redeemDetail(long redeemId, long tierId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> paramsRedeem = new HashMap<String, String>();
		paramsRedeem.put("RedeemDeliveryID", Long.toString(redeemId));
		paramsRedeem.put("CandidateContactID", Long.toString(6));
		paramsRedeem.put("TierLevelID", Long.toString(tierId));
		String jsonRedeem = new JSONObject(paramsRedeem).toString();

		excute(Urls.REDEEM_DETAIL,
				String.format("jsonValue=%s&token=%s", jsonRedeem, token),
				new MethodParams(Methods.getRedeemDetail));
	}

	public void inivationCode(String inivation) {
		excute(String.format(Urls.INVITATION,
				String.format("{\"AccessCode\":\"%s\"}", inivation)),
				new MethodParams(Methods.invitationCode));
	}

	public void login(String email, String password) {
		excute(String.format(Urls.LOGIN, String.format(
				"{\"username\":\"%s\",\"password\":\"%s\"}", email, password)),
				new MethodParams(Methods.Login));
	}

	public void changePassword(String email, String password) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("username", email);
		params.put("password", password);
		JSONObject json = new JSONObject(params);
		excute(Urls.CHANGE_PASS,
				String.format("jsonValue=%s&token=%s", json.toString(), token),
				new MethodParams(Methods.changePass));
	}

	public void resetPassword(String email) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("email", email);
		JSONObject json = new JSONObject(params);
		excute(Urls.FORGET_PASS,
				String.format("jsonValue=%s", json.toString()),
				new MethodParams(Methods.resetPass));
	}

	public void getAllDeal(int position, int size) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		excute(String.format(Urls.GET_ALL_DEAL, token, EMarketing.getInstance()
				.getAccountId(), position, size), new MethodParams(
				Methods.getAllDeal));
	}

	public void getDealByStage(int position, int size, String stage) {
		String token = EMarketing.getInstance().getJsonAccountToken();

		String paramJsonValue = String
				.format("{\"CreatedBy\":%s,\"StatusID\":\"%s\",\"position\":%s,\"size\":%s}",
						EMarketing.getInstance().getAccountId(), stage,
						Integer.toString(position), Integer.toString(size));

		excute(String.format(Urls.GET_DEALS_BY_STAGE, token, paramJsonValue),
				new MethodParams(Methods.getAllDeal));
	}

	public void getDealDetail(long dealId) {
		String token = EMarketing.getInstance().getJsonAccountToken();
		MethodParams param = new MethodParams(Methods.getDealDetail);
		param.setInputData(dealId);
		excute(String.format(Urls.GET_DEAL_DETAIL, token, dealId), param);
	}

	public void saveTip(long tipID) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("OwnerContactID", EMarketing.getInstance().getAccountId());
		params.put("TipID", Long.toString(tipID));
		String token = EMarketing.getInstance().getJsonAccountToken();
		JSONObject json = new JSONObject(params);
		excute(Urls.SAVE_TIP, "token=" + token + "&" + "jsonColumnValue="
				+ json.toString(), new MethodParams(Methods.saveTip));
	}

	public void searchTip(String key, int position, int size,
			Tip.Category category) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("keySearch", key);
		params.put("TipCategoryID", Integer.toString(category.toInt()));
		params.put("position", Integer.toString(position));
		params.put("size", Integer.toString(size));
		String token = EMarketing.getInstance().getJsonAccountToken();
		JSONObject json = new JSONObject(params);
		excute(Urls.SEARCH_TIP,
				"token=" + token + "&" + "jsonValue=" + json.toString(),
				new MethodParams(Methods.searchTip));
	}

	public void searchQuiz(String key, int position, int size,
			Quiz.Category category) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("QuizCampaignName", key);
		params.put("QuizCategoryID", Integer.toString(category.toInt()));
		params.put("position", Integer.toString(position));
		params.put("size", Integer.toString(size));
		String token = EMarketing.getInstance().getJsonAccountToken();
		JSONObject json = new JSONObject(params);
		excute(Urls.SEARCH_QUIZ,
				"token=" + token + "&" + "jsonValue=" + json.toString(),
				new MethodParams(Methods.searchQuiz));
	}

	// public void searchDeal(String key, String value, int start, int size) {
	// Map<String, String> paramSearch = new HashMap<String, String>();
	// paramSearch.put(key, value);
	// String token = EMarketing.getInstance().getJsonAccountToken();
	// JSONObject jsonSearch = new JSONObject(paramSearch);
	// Map<String, String> paramPage = new HashMap<String, String>();
	// paramPage.put("position", Integer.toString(start));
	// paramPage.put("size", Integer.toString(size));
	// JSONObject jsonPage = new JSONObject(paramPage);
	// excute(Urls.SEARCH_DEAL, String.format(
	// "token=%s&jsonConditionValue=%s&jsonNumberRow=%s", token,
	// jsonSearch.toString(), jsonPage.toString()), new MethodParams(
	// Methods.searchDeal));
	// }

	public void deleteDeal(long dealId) {
		Map<String, Long> paramDelete = new HashMap<String, Long>();
		paramDelete.put("DealID", dealId);
		JSONObject json = new JSONObject(paramDelete);
		String token = EMarketing.getInstance().getJsonAccountToken();
		excute(Urls.DELETE_DEAL,
				String.format("token=%s&jsonValue=%s", token, json.toString()),
				new MethodParams(Methods.deleteDeal));
	}

	// public void registerCGM(String registerId) {
	// Map<String, String> paramPage = new HashMap<String, String>();
	// paramPage.put("RegisterNumber", registerId);
	// paramPage.put("ContactID", EMarketing.getInstance().getAccountId());
	// JSONObject jsonPage = new JSONObject(paramPage);
	// excute(Urls.REGISTER_GCM, String.format("token=%s&jsonValue=%s",
	// EMarketing.getInstance().getJsonAccountToken(),
	// jsonPage.toString()), new MethodParams(Methods.registerGCM));
	// }

	public void getPresetAnswerQuiz(long quizId) {
		Map<String, String> paramPage = new HashMap<String, String>();
		paramPage.put("QuizReply.QuizCampaignID", Long.toString(quizId));
		paramPage.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(paramPage);
		String token = EMarketing.getInstance().getJsonAccountToken();
		MethodParams methodParam = new MethodParams(Methods.getPresetResultQuiz);
		methodParam.setInputData(quizId);
		excute(Urls.QUIZ_ANSWER,
				String.format("token=%s&jsonColumnValue=%s", token,
						json.toString()), methodParam);
	}

	public void getQuizResult(long quizId) {
		Map<String, String> paramPage = new HashMap<String, String>();
		paramPage.put("QuizCampaignID", Long.toString(quizId));
		paramPage.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(paramPage);
		String token = EMarketing.getInstance().getJsonAccountToken();
		MethodParams methodParam = new MethodParams(Methods.getQuizResult);
		excute(Urls.SEARCH_PRODUCT_MODEL,
				String.format("token=%s&jsonColumnValue=%s", token,
						json.toString()), methodParam);
	}

	public void searchProductModelOnline(String key) {
		MethodParams methodParam = new MethodParams(Methods.searchProductModel);

		Map<String, String> paramPage = new HashMap<String, String>();
		paramPage.put("ModelNo", key);
		JSONObject json = new JSONObject(paramPage);
		String token = EMarketing.getInstance().getAccessCode();
		String jsonToken = String.format("{\"token\":\"%s\"}", token);

		// excute(jsonToken, new MethodParams(
		// Methods.getAllDistributor));

		// excute(Urls.SEARCH_PRODUCT_MODEL,
		// String.format("token=%s&keyWordJsonValue=%s", token,
		// json.toString()), methodParam);

		excute(Urls.SEARCH_PRODUCT_MODEL,
				String.format("token=%s&keyWordJsonValue=%s", jsonToken,
						json.toString()), methodParam);
	}

	/**
	 * Always search from local
	 * 
	 * @param key
	 */
	public void searchProductModel(String key) {

		MethodParams methodParam = new MethodParams(Methods.searchProductModel);
		List<Product> lp = ProductModelDBHelper.searchProduct(key);

		DataResult result = new DataResult();

		result.setData(lp);
		result.setMethodParam(methodParam);

		setChanged();
		notifyObservers(result);
	}

	public void searchOpportunity(String key) {
		searchOpportunity(key, "");
	}

	public void searchOpportunity(String key, String statusFilter) {
		// Map<String, String> paramPage = new HashMap<String, String>();
		// paramPage.put("keyword", key);
		// paramPage.put("CreatedBy", EMarketing.getInstance().getAccountId());
		// JSONObject json = new JSONObject(paramPage);
		// String token = EMarketing.getInstance().getJsonAccountToken();
		// MethodParams methodParam = new
		// MethodParams(Methods.searchOpportunity);
		// excute(Urls.SEARCH_OPPORTUNITY,
		// String.format("token=%s&jsonValue=%s", token, json.toString()),
		// methodParam);

		MethodParams methodParam = new MethodParams(Methods.searchOpportunity);
		List<Project> lp = ProjectDBHelper.searchProjects(key);

		DataResult result = new DataResult();

		if (!statusFilter.equals("")) {
			List<String> items = Arrays.asList(statusFilter.split("\\s*,\\s*"));

			for (Iterator<Project> it = lp.iterator(); it.hasNext();) {
				Project p = it.next();

				if (items.contains(p.getStatus()))
					continue;

				it.remove();
			}
		}

		result.setData(lp);
		result.setMethodParam(methodParam);

		setChanged();
		notifyObservers(result);
	}

	public void searchClaim(String key) {

		MethodParams methodParam = new MethodParams(Methods.searchClaim);
		List<Claim> lc = ClaimDBHelper.searchClaims(key);

		DataResult result = new DataResult();

		result.setData(lc);
		result.setMethodParam(methodParam);

		setChanged();
		notifyObservers(result);
	}

	public void syncProjectsToServer(List<Project> pjs) {

		JSONArray arrayRecord = new JSONArray();
		MethodParams methodParam = new MethodParams(Methods.projectsSync);

		ArrayList<String> ids = new ArrayList<String>();

		for (Project p : pjs) {
			Map<String, String> params = new HashMap<String, String>();

			params.put("CreatedBy", EMarketing.getInstance().getAccountId());

			// from this point now is the sync with the server side
			String pid = p.getId();
			ids.add(pid);
			params.put("OpportunityID", pid);

			// from this point here is the api preparation/call
			params.put("ItemStatus", p.getStatus());

			params.put("OpportunityName", p.getName());

			params.put("EndCustomerCompany", p.getCustomerCompanyName());

			params.put("TotalEstimatedAmount", Integer.toString(p.getAmount()));

			params.put("isCreate", p.isNewInsert() ? "true" : "false");

			String date = "";
			if (p.getDate() != 0) {
				Calendar cal = Calendar.getInstance();
				cal.setTimeInMillis(p.getDate());
				date = String.format("%s/%s/%s", cal.get(Calendar.MONTH) + 1,
						cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.YEAR));
			}

			params.put("ExpectedClosingDate", date);

			JSONObject jsonRecordValue = new JSONObject(params);
			arrayRecord.put(jsonRecordValue);
		}

		// set array string data
		methodParam.setTag(Constant.ID_LOCAL, ids.toArray());

		String token = EMarketing.getInstance().getJsonAccountToken();

		excute(Urls.SYNC_PROJECTS,
				String.format("token=%s&JsonValue=%s", token,
						arrayRecord.toString()), methodParam);
	}

	/**
	 * 
	 * Insert a new Opportunity depend on submit or save
	 * 
	 * @param project
	 * @param method
	 */
	private void syncProject(Project project, Methods method) {

		switch (method) {
		case createOpportunity:
			project.setStatus(ItemStatus.PENDING);
			break;
		case saveOpportunity:
			project.setStatus(ItemStatus.DRAFT);
			break;
		default:
			break;
		}

		MethodParams methodParam = new MethodParams(method);

		if (project.getStatus().equals(ItemStatus.PENDING)) {
			if (!EMarketing.isOnline()) {
				DataResult result = new DataResult();

				methodParam.setInputData("No Internet Connection");
				// notify the observers
				result.setMethodParam(methodParam);
				setChanged();
				notifyObservers(result);
				return;
			}

		}

		// store the submit status to methodParam
		methodParam.setInputData(project.getStatus());

		// turn on the cache mode
		methodParam.setOnly4Cache(true);

		String pid = project.getId();
		System.out.println(">>>> id = " + pid);
		if (Constant.CHECK_DELETED_DRAFT) {
			project.setStatus(ItemStatus.DELETE);
			Constant.CHECK_DELETED_DRAFT = false;
		}
		if (pid.equals("")) {
			pid = UUID.randomUUID().toString();
			project.setId(pid);
			project.setNewInsert(true);
		}

		// store to the local storage at first
		String localid = ProjectDBHelper.insertUpdateProject(project, false);

		DataResult result = new DataResult();
		// set array string data
		methodParam.setTag(Constant.ID_LOCAL, new String[] { localid });

		result.setMethodParam(methodParam);

		ArrayList<String> idslist = new ArrayList<String>();
		idslist.add(pid);
		result.setData(idslist);

		// notify the observers
		setChanged();
		notifyObservers(result);

		// from this point now is the sync with the server side
		/**
		 * ----------------------------- SERVER SYNC
		 * -----------------------------
		 */
		Map<String, String> params = new HashMap<String, String>();

		params.put("CreatedBy", EMarketing.getInstance().getAccountId());

		params.put("OpportunityID", pid);

		params.put("ItemStatus", project.getStatus());

		params.put("OpportunityName", project.getName());

		params.put("EndCustomerCompany", project.getCustomerCompanyName());

		params.put("TotalEstimatedAmount",
				Integer.toString(project.getAmount()));

		// check in the DB one more time to make sure that this is new insert
		Project temp = ProjectDBHelper.getProjectById(pid);

		if (temp != null)
			params.put("isCreate", temp.isNewInsert() ? "true" : "false");
		else
			params.put("isCreate", project.isNewInsert() ? "true" : "false");

		params.put(Constant.ID_LOCAL, localid);

		String date = "";
		if (project.getDate() != 0) {
			Calendar cal = Calendar.getInstance();
			cal.setTimeInMillis(project.getDate());
			date = String.format("%s/%s/%s", cal.get(Calendar.MONTH) + 1,
					cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.YEAR));
		}

		params.put("ExpectedClosingDate", date);

		JSONArray arrayRecord = new JSONArray();
		JSONObject jsonRecordValue = new JSONObject(params);
		arrayRecord.put(jsonRecordValue);

		String token = EMarketing.getInstance().getJsonAccountToken();

		excute(Urls.SYNC_PROJECTS,
				String.format("token=%s&JsonValue=%s", token,
						arrayRecord.toString()), methodParam);
	}

	public void updateProject(Project project) {
		syncProject(project, Methods.updateOpportunity);
	}

	public void createProject(Project project) {
		syncProject(project, Methods.createOpportunity);
	}

	public void saveProject(Project project) {
		syncProject(project, Methods.saveOpportunity);
	}

	/**
	 * delete an opportunity
	 * 
	 * @param id
	 */
	public void deleteOpportunity(long id) {
		Map<String, Long> paramDelete = new HashMap<String, Long>();

		paramDelete.put("OpportunityID", id);

		JSONObject json = new JSONObject(paramDelete);

		String token = EMarketing.getInstance().getJsonAccountToken();

		excute(Urls.DELETE_OPPORTUNITY,
				String.format("token=%s&jsonValue=%s", token, json.toString()),
				new MethodParams(Methods.deleteOpportunity));
	}

	/**
	 * 
	 * @param status
	 */
	public void getOpportunityByStatus(String status, String tagname) {

		MethodParams methodParam = new MethodParams(
				Methods.getOpportunityByStatus);
		List<Project> lp = ProjectDBHelper.getProjectsByStatus(status);

		if (lp.size() >= 1) {
			DataResult result = new DataResult();

			methodParam.setInputData(tagname);
			methodParam.setOnly4Cache(true);

			result.setData(lp);
			result.setMethodParam(methodParam);

			setChanged();
			notifyObservers(result);
		}

		Map<String, String> param = new HashMap<String, String>();

		param.put("status", status);
		param.put("CreatedBy", EMarketing.getInstance().getAccountId());

		JSONObject json = new JSONObject(param);
		String token = EMarketing.getInstance().getJsonAccountToken();

		methodParam.setInputData(tagname);

		excute(Urls.GET_OPPORTUNITY_BY_STATUS,
				String.format("token=%s&jsonValue=%s", token, json.toString()),
				methodParam);
	}

	public void getProjectDetail(String id) {

		Project p = ProjectDBHelper.getProjectById(id);

		if (p != null) {

			MethodParams methodParam = new MethodParams(
					Methods.getOpportunityDetail);
			methodParam.setOnly4Cache(true);
			methodParam.setInputData(id);

			DataResult result = new DataResult();
			result.setData(p);
			result.setMethodParam(methodParam);

			setChanged();
			notifyObservers(result);

			if (!id.equals("")) {

				// still update to get new project detail
				Map<String, String> param = new HashMap<String, String>();

				param.put("OpportunityID", id);

				JSONObject json = new JSONObject(param);
				String token = EMarketing.getInstance().getJsonAccountToken();

				excute(Urls.GET_OPPORTUNITY_DETAIL,
						String.format("token=%s&jsonValue=%s", token,
								json.toString()), methodParam);
			}
		} else {
			// return error DataResult
		}
	}

	public void getClaimByStatus(String status, String tagname) {

		MethodParams methodParam = new MethodParams(Methods.getClaimByStatus);

		methodParam.setInputData(tagname);

		List<Claim> lc = ClaimDBHelper.getClaimByStatus(status);
		System.out.println("From local <<< " + lc.size());

		if (lc.size() >= 1) {

			if (SPreferences.hasFetchedData(ClaimDBHelper.TABLE_NAME)
					|| !EMarketing.isOnline()) {
				DataResult result = new DataResult();

				methodParam.setInputData(tagname);
				methodParam.setOnly4Cache(true);

				result.setData(lc);
				result.setMethodParam(methodParam);

				setChanged();
				notifyObservers(result);
			}

		}

		Map<String, String> param = new HashMap<String, String>();

		param.put("status", status);
		param.put("CreatedBy", EMarketing.getInstance().getAccountId());

		JSONObject json = new JSONObject(param);
		String token = EMarketing.getInstance().getJsonAccountToken();

		methodParam.setInputData(tagname);

		excute(Urls.GET_CLAIM_BY_STATUS,
				String.format("token=%s&jsonValue=%s", token, json.toString()),
				methodParam);
	}

	public void getClaimDetail(String mLocalId) {

		Claim c = ClaimDBHelper.getClaimByLocalId(mLocalId);
		if (c != null) {
			long id = c.getId();
			// Constant.id_Claim = id;
			MethodParams methodParam = new MethodParams(Methods.getClaimDetail);
			methodParam.setOnly4Cache(true);
			methodParam.setInputData(id);

			DataResult result = new DataResult();
			result.setData(c);
			result.setMethodParam(methodParam);

			setChanged();
			notifyObservers(result);

			if (id != 0) {

				// still update to get new project detail
				Map<String, String> param = new HashMap<String, String>();

				param.put("ClaimID", Long.toString(id));

				JSONObject json = new JSONObject(param);
				String token = EMarketing.getInstance().getJsonAccountToken();

				excute(Urls.GET_CLAIM_DETAIL,
						String.format("token=%s&jsonValue=%s", token,
								json.toString()), methodParam);
			}

		} else {
		}
	}

	public void syncClaimToServer(Claim c) {

		if (c.getStatus().equals(""))
			return;

		Methods m = Methods.updateClaim;

		if (c.getId() == 0)
			if (c.getStatus().equals(ItemStatus.SUBMITTED))
				m = Methods.createClaim;
			else if (c.getStatus().equals(ItemStatus.DRAFT))
				m = Methods.saveClaim;

		syncClaim(c, m, true);
	}

	/**
	 * insert a new claim to (including of submit and save draft)
	 * 
	 * @param listUri
	 * @param claim
	 * @param method
	 */
	private void syncClaim(Claim claim, final Methods method,
			final boolean isSyncToServer) {

		new AsyncTask<Claim, Void, Void>() {

			@Override
			protected Void doInBackground(Claim... params) {

				try {

					Claim c = params[0];

					switch (method) {

					case createClaim:
						c.setStatus(ItemStatus.SUBMITTED);
						break;
					case saveClaim:
						c.setStatus(ItemStatus.DRAFT);
						break;
					default:
						break;
					}

					MethodParams methodParam = new MethodParams(method);

					if (c.getStatus().equals(ItemStatus.SUBMITTED)) {

						if (!EMarketing.isOnline()) {
							DataResult result = new DataResult();

							methodParam.setInputData("No Internet Connection");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;

						}

						if (c.getInvoiceNo().length() == 0) {
							DataResult result = new DataResult();
							methodParam
									.setInputData("Please Enter Invoice No.");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						if (c.getImages().size() == 0) {

							DataResult result = new DataResult();

							methodParam.setInputData("Please Upload Picture");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						if (String.valueOf(c.getDate()).trim().length() == 0) {

							DataResult result = new DataResult();

							methodParam
									.setInputData("Please Enter Invoice Date");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						if (c.getDistributorId() == 0) {

							DataResult result = new DataResult();

							methodParam
									.setInputData("Please Select Distributor Name");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						if (c.getProducts().size() == 0) {
							DataResult result = new DataResult();
							methodParam.setInputData("Please fill the Detail");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						for (int i = 0; i < c.getProducts().size(); i++) {
							if (c.getProducts().get(i).getProductId() == 0) {
								checkModelNo = true;
								break;
							}
						}

						if (checkModelNo) {
							checkModelNo = false;
							DataResult result = new DataResult();

							methodParam.setInputData("Please Enter Model No.");
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}

						for (int i = 0; i < c.getProducts().size(); i++) {
							int countServiceTag = getCount(c.getProducts()
									.get(i).getService_tag());
							if (c.getProducts().get(i).getService_tag()
									.toString().trim().length() == 0
									&& c.getProducts().get(i).getQuantity() > 0) {
								countServiceTag = -1;
							}
							if (!((countServiceTag + 1) == c.getProducts()
									.get(i).getQuantity())) {
								positionServiceTag = i;
								checkServiceTag = true;
								break;
								// Toast.makeText(mContext,
								// "Please Check Service Tags : Item " + (i +
								// 1), Toast.LENGTH_SHORT).show();
								// return false;
							}
						}

						if (checkServiceTag) {
							checkServiceTag = false;
							DataResult result = new DataResult();

							methodParam
									.setInputData("Please Check Service Tags : Item "
											+ (positionServiceTag + 1));
							// notify the observers
							result.setMethodParam(methodParam);
							setChanged();
							notifyObservers(result);
							return null;
						}
					}

					// turn on the cache mode
					methodParam.setOnly4Cache(true);

					String localid = "";

					if (c.getType().equals(Claim.TYPE_UNIT))
						c.setCustomerCompanyName("");

					// store to the local storage at first
					if (!isSyncToServer)
						localid = ClaimDBHelper.insertUpdateClaim(c, false);
					else
						localid = c.getLocalId();

					DataResult result = new DataResult();

					// set array string data
					methodParam.setTag(Constant.ID_LOCAL,
							new String[] { localid });

					result.setMethodParam(methodParam);
					result.setData(localid);

					// notify the observers
					setChanged();
					notifyObservers(result);

					// from this point now is the sync with the server side
					/**
					 * ----------------------------- SERVER SYNC
					 * -----------------------------
					 */

					String token = EMarketing.getInstance()
							.getJsonAccountToken();

					MultipartEntity reqEntity = new MultipartEntity(
							HttpMultipartMode.BROWSER_COMPATIBLE);

					// ------- claimHeaderJsonValue -------
					Map<String, String> paramHeader = new HashMap<String, String>();
					paramHeader.put("CreatedBy", EMarketing.getInstance()
							.getAccountId());
					paramHeader.put("CustomerInvoiceNo", c.getInvoiceNo());

					String date = "";
					if (c.getDate() != 0) {
						Calendar cal = Calendar.getInstance();
						cal.setTimeInMillis(c.getDate());
						date = String.format("%s/%s/%s",
								cal.get(Calendar.MONTH) + 1,
								cal.get(Calendar.DAY_OF_MONTH),
								cal.get(Calendar.YEAR));
					}

					paramHeader.put("CustomerInvoiceDate", date);

					paramHeader.put("CustomerCompanyName",
							c.getCustomerCompanyName());

					paramHeader.put("OpportunityID", c.getOpportunityId()
							.equals("") ? "NULL" : c.getOpportunityId());

					paramHeader.put("Total", c.getTotal() == 0 ? "NULL"
							: Double.toString(c.getTotal()));

					paramHeader.put("ClaimType", c.getType());

					String cid = (c.getId() == 0) ? "" : Long.toString(c
							.getId());
					paramHeader.put("ClaimID", cid);

					paramHeader.put(Constant.ID_LOCAL, localid);

					paramHeader.put("ClaimStatus", c.getStatus());

					paramHeader.put("DistributorID",
							Long.toString(c.getDistributorId()));

					JSONObject jsonHeader = new JSONObject(paramHeader);

					// ------- claimDetailJsonValue -------

					List<Product> products = c.getProducts();
					JSONObject jsonProductValue = new JSONObject();

					if (products != null && products.size() > 0) {
						JSONArray arrayProduct = new JSONArray();
						for (Product product : products) {
							Map<String, String> paramProduct = new HashMap<String, String>();

							paramProduct.put("UnitPrice",
									Float.toString(product.getPrice()));

							paramProduct.put("ProductID",
									Long.toString(product.getProductId()));
							paramProduct.put("Quantity",
									Integer.toString(product.getQuantity()));
							paramProduct.put("SeriveTag",
									(product.getService_tag()));
							JSONObject jsonProduct = new JSONObject(
									paramProduct);
							arrayProduct.put(jsonProduct);
						}

						jsonProductValue.put("product", arrayProduct);

					}

					// set token
					reqEntity.addPart("token", new StringBody(token));

					// set claim header values
					reqEntity.addPart("claimHeaderJsonValue", new StringBody(
							jsonHeader.toString()));

					// set claim products values
					reqEntity.addPart("claimDetailJsonValue", new StringBody(
							jsonProductValue.toString()));

					// ------- imageDegreeJsonValue -------

					JSONObject degree = new JSONObject();
					JSONArray arrayDegree = new JSONArray();

					JSONObject remove = new JSONObject();
					JSONArray arrayRemove = new JSONArray();

					JSONArray arrayUpdate = new JSONArray();

					for (ClaimImage ci : c.getImages()) {

						if (ci.getClaimImageId() != 0) {

							if (ci.isDelete())
								arrayRemove.put(Long.toString(ci
										.getClaimImageId()));
							else {

								Map<String, String> paramUpdateImages = new HashMap<String, String>();

								paramUpdateImages.put("ImageID",
										Long.toString(ci.getClaimImageId()));

								paramUpdateImages.put("Degree",
										Integer.toString(ci.getRotateDegree()));

								JSONObject update = new JSONObject(
										paramUpdateImages);
								arrayUpdate.put(update);
							}

							continue;
						}

						Bitmap image = Utility.getBitmapFromUri(EMarketing
								.getInstance().getApplicationContext(), ci
								.getImageLocation());

						ByteArrayOutputStream stream = new ByteArrayOutputStream();
						image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
						byte[] data_image = stream.toByteArray();

						ByteArrayBody bab = new ByteArrayBody(data_image,
								String.format("%s_Claim_%s", Utility.uRLfix(c
										.getCustomerCompanyName()), ci
										.getImageLocation()
										.getLastPathSegment()));

						reqEntity.addPart(ci.getImageLocation()
								.getLastPathSegment(), bab);

						arrayDegree.put(Integer.toString(ci.getRotateDegree()));

					}

					degree.put("Degree", arrayDegree);
					reqEntity.addPart("imageDegreeJsonValue", new StringBody(
							degree.toString()));

					remove.put("ImageID", arrayRemove);
					reqEntity.addPart("deleteImageListJsonValue",
							new StringBody(remove.toString()));

					reqEntity.addPart("updateImageListJsonValue",
							new StringBody(arrayUpdate.toString()));

					Log.e(TAG, " claimHeaderJsonValue " + jsonHeader.toString());
					Log.e(TAG,
							" claimDetailJsonValue "
									+ jsonProductValue.toString());
					Log.e(TAG, " imageDegreeJsonValue " + degree.toString());
					Log.e(TAG, " deleteImageListJsonValue " + remove.toString());
					Log.e(TAG,
							" updateImageListJsonValue "
									+ arrayUpdate.toString());

					String Url = "";
					switch (method) {
					case deleteClaim:
					case updateClaim:
						Url = Urls.UPDATE_CLAIM;
						break;
					default:
						Url = Urls.CREATE_CLAIM;
						break;
					}

					// actually call to WebService to do the update
					HttpPost httpPost = new HttpPost(Url);
					httpPost.setEntity(reqEntity);

					HttpClient httpClient = new DefaultHttpClient();
					HttpResponse response = httpClient.execute(httpPost);

					BufferedReader reader = new BufferedReader(
							new InputStreamReader(response.getEntity()
									.getContent(), "UTF-8"));
					String sResponse;
					StringBuilder s = new StringBuilder();

					while ((sResponse = reader.readLine()) != null) {
						s = s.append(sResponse);
					}

					String output = s.toString();

					output = output.replace(
							"<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
					output = output.replace(
							"<string xmlns=\"http://tempuri.org/\">", "");
					output = output.replace("</string>", "");

					DataResult syncresult = ParserDataHelper.getInstance()
							.parse(output, methodParam);

					if ((syncresult == null) || methodParam.isOnly4Cache())
						return null;

					result.setMethodParam(methodParam);
					setChanged();
					notifyObservers(syncresult);

					Log.e(TAG, "Response: " + s);
				} catch (UnsupportedEncodingException e) {
					Log.e(TAG, e.toString());
				} catch (ClientProtocolException e) {
					Log.e(TAG, e.toString());
				} catch (IOException e) {
					Log.e(TAG, e.toString());
				} catch (JSONException e) {
					Log.e(TAG, e.toString());
				}

				return null;
			}

		}.execute(claim);
	}

	/**
	 * submit a new claim
	 * 
	 * @param listUri
	 * @param claim
	 */
	public void createClaim(Claim claim) {
		syncClaim(claim, Methods.createClaim, false);
	}

	/**
	 * save new claim to draft
	 * 
	 * @param listUri
	 * @param claim
	 */
	public void saveClaim(Claim claim) {
		syncClaim(claim, Methods.saveClaim, false);
	}

	public void updateClaim(Claim claim) {
		syncClaim(claim, Methods.updateClaim, false);
	}

	/**
	 * 
	 * @param id
	 */
	public void deleteClaim(String localClaimId) {

		int dresult = ClaimDBHelper.deleteClaim(localClaimId);

		if (dresult == 0) {
			// delete a already synced claim
			Claim c = ClaimDBHelper.getClaimByLocalId(localClaimId);
			syncClaim(c, Methods.deleteClaim, true);
		} else if (dresult == 1) {
			// delete a already synced claim

			MethodParams mp = new MethodParams(Methods.deleteClaim);

			DataResult result = new DataResult();

			// set array string data
			mp.setTag(Constant.ID_LOCAL, new String[] { localClaimId });

			result.setMethodParam(mp);
			result.setData(localClaimId);

			// notify the observers
			setChanged();
			notifyObservers(result);
		}

		// Map<String, Long> paramDelete = new HashMap<String, Long>();
		//
		// paramDelete.put("ClaimID", id);
		//
		// JSONObject json = new JSONObject(paramDelete);
		//
		// String token = EMarketing.getInstance().getJsonAccountToken();
		//
		// excute(Urls.DELETE_CLAIM,
		// String.format("token=%s&jsonValue=%s", token, json.toString()),
		// new MethodParams(Methods.deleteClaim));
	}

	// author Tam
	public void getPriceBook() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> param = new HashMap<String, String>();
		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getPriceBook);
		excute(Urls.GET_PRICE_BOOK,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getPromotion() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> param = new HashMap<String, String>();
		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getPromotion);
		excute(Urls.GET_PROMOTION,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getProductImage() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		Map<String, String> param = new HashMap<String, String>();
		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getProductImage);
		excute(Urls.GET_PRODUCT_IMAGE,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getReward() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// still update to get new project detail
		Map<String, String> param = new HashMap<String, String>();

		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getReward);
		excute(Urls.GET_REWARD,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getRewardProject() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// still update to get new project detail
		Map<String, String> param = new HashMap<String, String>();

		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getRewardProject);
		excute(Urls.GET_REWARD_PROJECT,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getRewardClaim() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// still update to get new project detail
		Map<String, String> param = new HashMap<String, String>();

		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(Methods.getRewardClaim);
		excute(Urls.GET_REWARD_CLAIM,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getRewardProjectDetail() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// still update to get new project detail
		Map<String, String> param = new HashMap<String, String>();

		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(
				Methods.getRewardProjectDetail);
		excute(Urls.GET_REWARD_PROJECT_DETAIL,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	public void getRewardClaimDetail() {
		String token = EMarketing.getInstance().getJsonAccountToken();
		// still update to get new project detail
		Map<String, String> param = new HashMap<String, String>();

		param.put("PartnerID", EMarketing.getInstance().getAccountId());
		JSONObject json = new JSONObject(param);
		MethodParams methodParam = new MethodParams(
				Methods.getRewardClaimDetail);
		excute(Urls.GET_REWARD_CLAIM_DETAIL,
				String.format("token=%s&jsonValue=%s", token, json),
				methodParam);
	}

	/**
	 * Actually create an Internet call to fetch data
	 * 
	 * @param conn
	 * @param postData
	 * @param methodParams
	 * @return
	 * @throws SocketTimeoutException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private DataResult request(HttpURLConnection conn, String postData,
			MethodParams methodParams) throws SocketTimeoutException,
			FileNotFoundException, IOException {
		DataResult result;
		if (postData != null) {

			Log.e(TAG, conn.getURL().toString() + "?" + postData);

			conn.setRequestMethod("POST");
			conn.setDoOutput(true);
			OutputStream out = new BufferedOutputStream(conn.getOutputStream());
			out.write(postData.getBytes());
			out.flush();
			out.close();
		} else {

			Log.e(TAG, conn.getURL().toString());

			conn.setRequestMethod("GET");
		}

		int httpCode = conn.getResponseCode();

		Log.e(TAG, "http response code " + httpCode);

		if (httpCode == HttpURLConnection.HTTP_OK
				|| httpCode == HttpURLConnection.HTTP_CREATED) {
			InputStream in = new BufferedInputStream(conn.getInputStream());
			String content = ConvertStreamToString(in);
			in.close();
			content = content.replace(
					"<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
			content = content.replace("<string xmlns=\"http://tempuri.org/\">",
					"");
			content = content.replace("</string>", "");

			result = ParserDataHelper.getInstance()
					.parse(content, methodParams);

			if ((result == null) || methodParams.isOnly4Cache())
				return null;

			result.setMethodParam(methodParams);
			return result;
		} else {
			result = new DataResult();
			result.setMethodParam(methodParams);
			result.setErrorCode(ErrorCode.SERVER_ERROR);
		}
		return result;
	}

	private class HttpTask extends AsyncTask<Void, Void, DataResult> {
		MethodParams mMethodParam;
		String mHttpUrl;
		String mDataPost;
		HttpURLConnection mHttpUrlConnection;

		public HttpTask(String url, MethodParams params) {
			mHttpUrl = url;
			mMethodParam = params;
		}

		public HttpTask(String url, MethodParams params, String datapost) {
			mHttpUrl = url;
			mDataPost = datapost;
			mMethodParam = params;
		}

		public String getUrl() {
			return mHttpUrl;
		}

		public void disconect() {
			if (mHttpUrlConnection != null)
				mHttpUrlConnection.disconnect();
			cancel(true);
			mWaitingTask.add(new HttpTask(mHttpUrl, mMethodParam, mDataPost));
			Log.e(TAG, "waiting queue size: " + mWaitingTask.size());

		}

		@Override
		protected DataResult doInBackground(Void... params) {
			try {

				if (!EMarketing.isOnline())
					if (mMethodParam.isOnly4Cache())
						return null;

				System.setProperty("http.keepAlive", "false");
				URL u = new URL(mHttpUrl);
				mHttpUrlConnection = (HttpURLConnection) u.openConnection();
				mHttpUrlConnection.setConnectTimeout(TIME_OUT_CONNECTION);
				mHttpUrlConnection.setReadTimeout(TIME_OUT_CONNECTION);
				mHttpUrlConnection.setDoInput(true);
				return request(mHttpUrlConnection, mDataPost, mMethodParam);
			} catch (FileNotFoundException e) {
				DataResult result = new DataResult();
				result.setErrorCode(ErrorCode.SERVER_ERROR);
				result.setMethodParam(mMethodParam);
				Log.e(TAG, "Server Error");
				return result;
			} catch (SocketTimeoutException e) {
				DataResult result = new DataResult();
				result.setErrorCode(ErrorCode.TIME_OUT);
				result.setMethodParam(mMethodParam);
				Log.e(TAG, "Time Out");
				return result;
			} catch (IOException e) {
				DataResult result = new DataResult();
				result.setErrorCode(ErrorCode.NETWORK_ERROR);
				result.setMethodParam(mMethodParam);
				Log.e(TAG, "IOException");
				return result;
			} finally {
				// actually disconnect the request
				if (mHttpUrlConnection != null) {
					mHttpUrlConnection.disconnect();
				}
			}
		}

		@SuppressLint("NewApi")
		@Override
		protected void onPostExecute(DataResult result) {

			mPoolExcutingTask.remove(mHttpUrl);
			if (mPoolExcutingTask.size() < MAX_SIZE_POOL) {
				HttpTask task = mWaitingTask.poll();
				if (task != null) {
					mPoolExcutingTask.put(task.getUrl(), task);
					if (android.os.Build.VERSION.SDK_INT >= 11) {
						task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
								(Void) null);
					} else {
						task.execute((Void) null);
					}
				}
			}

			if (result != null) {
				setChanged();
				notifyObservers(result);
			} else {
				Log.w(TAG, "http task result = null");
			}
		}
	}

	private int getCount(String charList) {
		int ct = 0;
		for (int i = 0; i < charList.length(); i++) {
			// c = charList.get(i); //why were you doing this, this method takes
			// the desired c as an input?
			if (",".contains(String.valueOf(charList.charAt(i)))) { // now it
																	// only
																	// incriments
																	// when that
																	// particular
																	// entry
																	// equals c,
																	// not if
																	// ANY entry
																	// matches c
				ct++;
			}
		}
		return ct;
	}
}
